package com.itfreer.file.service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.stereotype.Component;

import com.itfreer.file.AnalyseFilePathPara;
import com.itfreer.file.FileSegmentInfo;
import com.itfreer.file.IAnalyseFileService;
import com.itfreer.file.IAnalyseUploadFileServe;

/**
 * 文件上传解析服务器
 * 
 * @author gj
 *
 */
@Component(value = "fileAnalyseUploadService")
@Path("/fileAnalyse/plupload")
public class FileAnalyseUploadService {
	@Autowired
	private IAnalyseUploadFileServe fileService;

	@Autowired
	DefaultListableBeanFactory beanFactory;

	@Autowired(required = false)
	private AnalyseFilePathPara uploadPara;

	private AnalyseFilePathPara getUploadPara() {
		if (uploadPara == null) {
			uploadPara = new AnalyseFilePathPara();
		}
		return uploadPara;
	}

	/**
	 * 文件上传
	 * 
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	@POST
	@Path("/uploadFile")
	@Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
	public String uploadFile(@Context HttpServletRequest request, @Context HttpServletResponse response)
			throws ServletException, IOException {

		// 1、创建一个文件上传解析器
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// threshold 极限、临界值，即硬盘缓存 1M
		factory.setSizeThreshold(1024);

		ServletFileUpload upload = new ServletFileUpload(factory);
		// 设置允许上传的最大文件大小（单位MB）
		upload.setSizeMax(getUploadPara().getMaxSize());
		upload.setHeaderEncoding("UTF-8");

		// 2、判断提交上来的数据是否是上传表单的数据
		if (!ServletFileUpload.isMultipartContent(request)) {
			return "{\"status\":false}";
		}

		// 3、使用ServletFileUpload解析器解析上传数据，解析结果返回的是一个List<FileItem>集合，每一个FileItem对应一个Form表单的输入项
		try {
			List<FileItem> list = upload.parseRequest(request);
			HashMap<String, Object> map = new HashMap<String, Object>();
			for (FileItem item : list) {
				if (item.isFormField()) {
					// 普通输入项
					String name = item.getFieldName();
					if ("name".equals(name)) {
						String fileName = Streams.asString(item.getInputStream(), "UTF-8");
						fileName = new String(fileName.getBytes("iso8859-1"), "UTF-8");
						map.put(name, fileName);
					} else if ("chunk".equals(name)) {
						map.put(name, Streams.asString(item.getInputStream()));
					} else if ("chunks".equals(name)) {
						map.put(name, Streams.asString(item.getInputStream()));
					}
				} else {
					// 文件内容
					map.put("content", item.getInputStream());
				}
			}

			// 此文件名是前端控件已转换后唯一的名称，非上传文件原名称
			String fileName = map.get("name").toString();
			int chunks = 0;
			if (map.containsKey("chunks")) {
				chunks = Integer.parseInt(map.get("chunks").toString());
			}
			int chunk = 0;
			if (map.containsKey("chunk")) {
				chunk = Integer.parseInt(map.get("chunk").toString());
			}

			InputStream inputStearm = (InputStream) map.get("content");
			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
			byte[] buff = new byte[1024];
			int rc = 0;
			while ((rc = inputStearm.read(buff, 0, 1024)) > 0) {
				swapStream.write(buff, 0, rc);
			}
			byte[] content = swapStream.toByteArray();

			// 创建存储块
			String bucketName = getUploadPara().getBucketName();
			fileService.createBucket(bucketName);

			// 创建存储文件的目录 ，规则为:当前日期/guid/原文件名
			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
			String ymd = sdf.format(new Date());
			String objectKey = ymd + "/";
			fileService.createDir(bucketName, objectKey);
			objectKey += fileName;

			// 配置文件大小，需和前台同步
			int segmentSize = getUploadPara().getSegmentSize();

			FileSegmentInfo fileSegmentInfo = new FileSegmentInfo();
			fileSegmentInfo.setSegmentContent(content);
			fileSegmentInfo.setSegmentIndex(chunk);
			fileSegmentInfo.setSegmentSize(segmentSize);
			fileSegmentInfo.setFileLength(segmentSize * chunks);

			String function = request.getParameter("function");
			Map<String, String[]> params = request.getParameterMap();

			if (function == null && "".equals(function)) {
				return "{\"status\":false}";
			}

			String newFilePath = fileService.uploadFile(bucketName, objectKey, fileSegmentInfo, null);
			if (newFilePath == null || "".equals(newFilePath)) {
				return "{\"status\":false}";
			} else {
				Map<String, IAnalyseFileService> beans = beanFactory.getBeansOfType(IAnalyseFileService.class);
				Set<String> keys = beans.keySet();
				for (String key : keys) {
					IAnalyseFileService iService = (IAnalyseFileService) beans.get(key);
					if (iService != null) {
						Component com = iService.getClass().getAnnotation(Component.class);
						if (function.equals(com.value())) {
							final HttpSession httpSession = request.getSession(false);
							Object userEntity = httpSession != null ? httpSession.getAttribute("s_user") : null;
							return iService.analyseFile(params, newFilePath, userEntity);
						}
					}

				}
				return "{\"status\":false}";
			}
		} catch (FileUploadException e) {
			e.printStackTrace();
			return "{\"status\":false}";
		}
	}
}
